﻿using System;
using CoreComponents;
using Crowler.Model.CoreComponents;
using Crowler.Model.CoreComponents.DataAccess;
using Crowler.TestBase;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace Crowler.CoreComponents.Test
{
    [TestClass]
    public class BusinessServiceFacilityShould: TestBaseClass
    {
        private Mock<IBusinessService<string, string>> _businessServiceMock;
        private Mock<IDataAccessManager> _dataAccessManager;
        private Mock<IUnitOfWork> _unitOfWork;
        private BusinessServiceFacility<string, string, string, string> _facility;
        private Mock<IAppEnvironment> _appEnv;

        public override void TestInitialize()
        {
            _appEnv = new Mock<IAppEnvironment>();
            _dataAccessManager = new Mock<IDataAccessManager>();
            _unitOfWork = new Mock<IUnitOfWork>();
            _businessServiceMock = new Mock<IBusinessService<string, string>>();
            SetUpMocks();
            _facility = new BusinessServiceFacility<string, string, string, string>(_appEnv.Object);
        }

        private void SetUpMocks()
        {
            _appEnv.Setup(o => o.Resolve<IDataAccessManager>()).Returns(_dataAccessManager.Object);
            _appEnv.Setup(o => o.Resolve<IBusinessService<string, string>>()).Returns(_businessServiceMock.Object);


            _dataAccessManager.Setup(o => o.Start()).Returns(_unitOfWork.Object);
        }

        public override void TestCleanup()
        {
        }

        [TestMethod]
        public void ExecuteInternalLogic()
        {
            _facility.Execute();
            _businessServiceMock.Verify(o => o.Execute(),Times.Once());
        }

        [TestMethod]
        public void WrapInnerExecutionWithTransaction()
        {
            _facility.Execute();
            _dataAccessManager.Verify(o => o.Start(),Times.Once());
            _unitOfWork.Verify(o => o.Dispose(),Times.Once());
        }

        [TestMethod]
        public void PassExecutionExceptionToUnitOfWork()
        {
            _businessServiceMock.Setup(o => o.Execute()).Throws(new Exception());
            _facility.Execute();
            _unitOfWork.VerifySet(o => o.IsExecutionException = true, Times.Once());
        }

        [TestMethod]
        public void PassRequestParameterToTheService()
        {
            _facility.Execute();
            _businessServiceMock.VerifySet(o => o.ServiceRequest = null,Times.Once());
        }

        [TestMethod]
        public void FetchServiceResponseAfterExecution()
        {
            _facility.Execute();
            _businessServiceMock.VerifyGet(o => o.ServiceResponse, Times.Once());
        }

        [TestMethod]
        public void InitializeDefaultResponse()
        {
            _facility.Execute();
            _businessServiceMock.Verify(o => o.InitializeDefaultResponse(),Times.Once());
        }
    }
}
